﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Dokan;
using RemoteCode.Attributes;

namespace MirrorDrive.Operations
{
    [Shareable]
    public class ServerOperations
    {
        private DokanOperations _prevLayer;

        public ServerOperations(DokanOperations prevLayer)
        {
            _prevLayer = prevLayer;
        }
       
        [RemoteExecutable]
        public ReturnObject CreateFile(string filename, System.IO.FileAccess access, System.IO.FileShare share, System.IO.FileMode mode, System.IO.FileOptions options, DokanFileInfo info)
        {
            int ret = _prevLayer.CreateFile(filename, access, share, mode, options, info);
            return new ReturnObject(null, info, ret);
        }

        [RemoteExecutable]
        public ReturnObject OpenDirectory(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.OpenDirectory(filename, info);
            return new ReturnObject(null, info, ret);
        }
        
        [RemoteExecutable]
        public ReturnObject CreateDirectory(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.CreateDirectory(filename, info);
            return new ReturnObject(null, info, ret);
        }
        
        [RemoteExecutable]
        public ReturnObject Cleanup(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.Cleanup(filename, info);
            return new ReturnObject(null, info, ret);
        }

        [RemoteExecutable]
        public ReturnObject CloseFile(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.CloseFile(filename, info);
            return new ReturnObject(null, info, ret);         
        }

        [RemoteExecutable]
        public ReturnObject ReadFile(string filename, byte[] buffer, long offset, DokanFileInfo info)
        {
            uint readBytes = 0;
            int ret = _prevLayer.ReadFile(filename, ref buffer, ref readBytes, offset, info);
            return new ReturnObject(new object[] { buffer, readBytes }, info, ret);             
        }

        [RemoteExecutable]
        public ReturnObject WriteFile(string filename, byte[] buffer, long offset, DokanFileInfo info)
        {
            uint writtenBytes = 0;
            int ret = _prevLayer.WriteFile(filename, buffer, ref writtenBytes, offset, info);
            return new ReturnObject(new object[] { writtenBytes }, info, ret);                
        }

        [RemoteExecutable]
        public ReturnObject FlushFileBuffers(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.FlushFileBuffers(filename, info);
            return new ReturnObject(null, info, ret);            
        }

        [RemoteExecutable]
        public ReturnObject GetFileInformation(string filename, DokanFileInfo info)
        {
            FileInformation fileinfo = new FileInformation();
            int ret = _prevLayer.GetFileInformation(filename, ref fileinfo, info);
            return new ReturnObject(new object[] { fileinfo }, info, ret);              
        }

        [RemoteExecutable]
        public ReturnObject FindFiles(string filename, DokanFileInfo info)
        {
            ArrayList files = new ArrayList();
            int ret = _prevLayer.FindFiles(filename, ref files, info);
            return new ReturnObject(new object[] { files }, info, ret);                 
        }

        [RemoteExecutable]
        public ReturnObject SetFileAttributes(string filename, System.IO.FileAttributes attr, DokanFileInfo info)
        {
            int ret = _prevLayer.SetFileAttributes(filename, attr, info);
            return new ReturnObject(null, info, ret);              
        }

        [RemoteExecutable]
        public ReturnObject SetFileTime(string filename, DateTime ctime, DateTime atime, DateTime mtime, DokanFileInfo info)
        {
            int ret = _prevLayer.SetFileTime(filename, ctime, atime, mtime, info);
            return new ReturnObject(null, info, ret);                        
        }

        [RemoteExecutable]
        public ReturnObject DeleteFile(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.DeleteFile(filename, info);
            return new ReturnObject(null, info, ret);              
        }

        [RemoteExecutable]
        public ReturnObject DeleteDirectory(string filename, DokanFileInfo info)
        {
            int ret = _prevLayer.DeleteDirectory(filename, info);
            return new ReturnObject(null, info, ret);                          
        }

        [RemoteExecutable]
        public ReturnObject MoveFile(string filename, string newname, bool replace, DokanFileInfo info)
        {
            int ret = _prevLayer.MoveFile(filename, newname, replace, info);
            return new ReturnObject(null, info, ret);              
        }

        [RemoteExecutable]
        public ReturnObject SetEndOfFile(string filename, long length, DokanFileInfo info)
        {
            int ret = _prevLayer.SetEndOfFile(filename, length, info);
            return new ReturnObject(null, info, ret);                         
        }

        [RemoteExecutable]
        public ReturnObject SetAllocationSize(string filename, long length, DokanFileInfo info)
        {
            int ret = _prevLayer.SetEndOfFile(filename, length, info);
            return new ReturnObject(null, info, ret);              
        }

        [RemoteExecutable]
        public ReturnObject LockFile(string filename, long offset, long length, DokanFileInfo info)
        {
            int ret = _prevLayer.LockFile(filename, offset, length, info);
            return new ReturnObject(null, info, ret);                         
        }

        [RemoteExecutable]
        public ReturnObject UnlockFile(string filename, long offset, long length, DokanFileInfo info)
        {
            int ret = _prevLayer.UnlockFile(filename, offset, length, info);
            return new ReturnObject(null, info, ret);                              
        }
        
        [RemoteExecutable]
        public ReturnObject GetDiskFreeSpace(DokanFileInfo info)
        {
            ulong freeBytesAvailable = 0, totalBytes = 0, totalFreeBytes = 0;
            int ret = _prevLayer.GetDiskFreeSpace(ref freeBytesAvailable, ref totalBytes, ref totalFreeBytes, info);
            return new ReturnObject(new object[] {freeBytesAvailable, totalBytes, totalFreeBytes}, info, ret);               
        }

        [RemoteExecutable]
        public ReturnObject Unmount(DokanFileInfo info)
        {
            int ret = _prevLayer.Unmount(info);
            return new ReturnObject(null, info, ret);               
        }
    }
}

